using System;
using System.Collections.Generic;
using System.Text;

using MCromwell.StaffIntranet.Core;
using MCromwell.StaffIntranet.DTO;
using MCromwell.StaffIntranet.Data.NHibernate;
using MCromwell.StaffIntranet.Task.Infrastructure;
using MCromwell.StaffIntranet.DependencyInjection;
using Mapper;

namespace MCromwell.StaffIntranet.Task.Tasks
{
    public class StaffViewingTask : AbstractTask, IStaffViewingTask

    {
        private IStaffRepository staffRepository;
        private ILookupRepository lookupRepository;

        public StaffViewingTask() 
            : base()
        {
            this.staffRepository = IoC.Resolve<IStaffRepository>();
            this.lookupRepository = IoC.Resolve<ILookupRepository>();
        }

        public StaffViewingTask(IStaffRepository staffRepository, ILookupRepository lookupRepository)
        {
            if (staffRepository == null)
                throw new ArgumentNullException("staff repository cannot be null");

            if (lookupRepository == null)
                throw new ArgumentNullException("lookup repository cannot be null");

            this.staffRepository = staffRepository;
            this.lookupRepository = lookupRepository;
        }

        [WrapExceptionWith(typeof(ProblemSearchingStaffException))]
        public IList<StaffDTO> SearchStaffUsing(string lastName, string firstName, int locationId, int StartRowIndex, int MaximumRowSize, out int total)
        {
            try
            {
                IList<StaffDTO> staffToReturn = new List<StaffDTO>();
                StaffSearchCriteria criteria = new StaffSearchCriteria();
                var mapper = SimpleObjectMapperContainer.RetrieveMapper<Staff, StaffDTO>();

                criteria.FirstName = firstName;
                criteria.LastName = lastName;
                criteria.LocationId = locationId;

                IList<Staff> staffFromRepository = staffRepository.WithPagingFindBy(criteria, StartRowIndex, MaximumRowSize, out total);
                if (staffFromRepository != null)
                {
                    foreach (Staff staff in staffFromRepository)
                    {
                        staffToReturn.Add(mapper.Apply(staff));
                    }
                }

                return staffToReturn;
            }
            catch (Exception ex)
            {
                Log(ex);
                throw new ProblemSearchingStaffException(ex);
            }
            
        }

        [WrapExceptionWith(typeof(ProblemViewingStaffException))]
        public StaffDTO RetrieveStaffDetailsFor(int id)
        {
            try
            {
                var mapper = SimpleObjectMapperContainer.RetrieveMapper<Staff, StaffDTO>();
                Staff foundStaff = staffRepository.FindBy(id);

                if (foundStaff == null) return null;
                
                return mapper.Apply(foundStaff);
            }
            catch (Exception ex)
            {
                Log(ex);
                throw new ProblemViewingStaffException(ex);
            }
            
        }

        [WrapExceptionWith(typeof(ProblemRetrievingAvailableLocationsException))]
        public IList<LocationDTO> RetrieveAvailableLocations()
        {
            try
            {
                IList<LocationDTO> locationsToReturn = new List<LocationDTO>();
                var mapper = SimpleObjectMapperContainer.RetrieveMapper<Location, LocationDTO>();
                IList<Location> availableLocations = lookupRepository.RetrieveLocations();
                foreach (Location location in availableLocations)
                {
                    locationsToReturn.Add(mapper.Apply(location));
                }

                return locationsToReturn;
            }
            catch (Exception ex)
            {
                Log(ex);
                throw new ProblemRetrievingAvailableLocationsException(ex);
            }
        }

    }
}
